package umg.os.kernel.scheduler;

import java.util.Comparator;

import umg.os.kernel.Dispatcher.DispatcherSwitchProcessListener;
import umg.os.process.ProcessControlBlock;
import umg.os.timer.Timer;
import umg.os.timer.Timer.TimerListener;

public abstract class Scheduler implements TimerListener, DispatcherSwitchProcessListener {
	
	private static Scheduler singletonInstance;
	
	protected Scheduler() {
		Timer.register(this);
	}
	
	/**
	 * Assigns the {@link Scheduler} for this execution, once an {@link Scheduler}
	 * has been set it cannot be changed. 
	 * 
	 * @param schedulerInstance.
	 * 
	 * The scheduler which will be used in this simulation.
	 * 
	 * @return
	 * <code>true</code> if and only the scheduler was successfully assigned.
	 */
 	public static boolean setSchedulerInstance(Scheduler schedulerInstance) {
		if (singletonInstance == null) {
			singletonInstance = schedulerInstance;
			return true;
		} else {
			return false;
		}
	}
	
	public static final Scheduler getInstance() {
		if (singletonInstance == null) { 
			throw new SchedulerNotAssignedException();
		}
		return singletonInstance;
	}
	
	public abstract ProcessControlBlock requestNextProcessToExecute();
	
	public abstract Comparator<ProcessControlBlock> getSorter();
	
	@SuppressWarnings("serial")
	public static class SchedulerNotAssignedException extends RuntimeException {
		
		protected SchedulerNotAssignedException() {
		}
		
		protected SchedulerNotAssignedException(String message) {
			super(message);
		}
		
	}
	
}
